home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / shells / bashsrc.zoo / variables.c < prev    next >
C/C++ Source or Header  |  1991-06-05  |  25KB  |  1,039 lines

  1. /* variables.c -- Functions for hacking shell variables. */
  2.  
  3. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU Bash, the Bourne Again SHell.
  6.  
  7. Bash is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 1, or (at your option) any later
  10. version.
  11.  
  12. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with Bash; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <pwd.h>
  24.  
  25. #include "shell.h"
  26. #include "flags.h"
  27. #include "version.h"
  28.  
  29. #ifdef SYSV
  30. struct passwd *getpwuid (), *getpwent ();
  31. #endif
  32.  
  33. /* The list of shell variables that the user has created, or that came from
  34.    the environment. */
  35. SHELL_VAR *variable_list;
  36.  
  37. /* The current variable context.  This is really a count of how deep into
  38.    executing functions we are. */
  39. int variable_context = 0;
  40.  
  41. /* The array of shell assignments which are made only in the environment
  42.    for a single command. */
  43. char **temporary_env = (char **)NULL;
  44.  
  45. /* Some funky variables which are known about specially.  Here is where
  46.    "$*", "$1", and all the cruft is kept. */
  47. char *dollar_vars[10];
  48. WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
  49.  
  50. /* The value of $$. */
  51. int dollar_dollar_pid;
  52.  
  53. /* An array which is passed to commands as their environment.  It is
  54.    manufactured from the overlap of the initial environment and the
  55.    shell variables that are marked for export. */
  56. char **export_env = (char **)NULL;
  57.  
  58. /* Non-zero means that we have to remake EXPORT_ENV. */
  59. int array_needs_making = 1;
  60.  
  61. /* The list of variables that may not be unset in this shell. */
  62. char **non_unsettable_vars = (char **)NULL;
  63.  
  64. #ifdef SYSV
  65. #define DEFAULT_MAIL_PATH "/usr/mail/"
  66. #else
  67. #define DEFAULT_MAIL_PATH "/usr/spool/mail/"
  68. #endif
  69.  
  70. /* Initialize the shell variables from the current environment. */
  71. initialize_shell_variables (env)
  72.      char *env[];
  73. {
  74.   extern char *primary_prompt, *secondary_prompt;
  75.   char *name, *string;
  76.   int c, char_index;
  77.   int string_index = 0;
  78.   SHELL_VAR *temp_var;
  79.  
  80.   while (string = env[string_index++])
  81.     {
  82.       char_index = 0;
  83.  
  84.       name = (char *)alloca (1 + strlen (string));
  85.  
  86.       while ((c = *string++) && c != '=')
  87.     name[char_index++] = c;
  88.  
  89.       name[char_index] = '\0';
  90.  
  91.       /* If exported function, define it now.  Sigh. */
  92.       if (strncmp ("() {", string, 4) == 0)
  93.     {
  94.       char *eval_string =
  95.         (char *)xmalloc (3 + strlen (string) + strlen (name));
  96.       sprintf (eval_string, "%s %s", name, string);
  97.       parse_and_execute (eval_string, name);
  98.     }
  99.       else
  100.     bind_variable (name, string);
  101.  
  102.       set_var_auto_export (name);
  103.     }
  104.  
  105.   /* Remember this pid. */
  106.   dollar_dollar_pid = getpid ();
  107.  
  108.   /* Now make our own defaults in case the vars that we think are
  109.      important are missing. */
  110.   set_if_not ("PATH", DEFAULT_PATH_VALUE);
  111.   set_var_auto_export ("PATH");
  112.  
  113.   set_if_not ("TERM", "dumb");
  114.   set_var_auto_export ("TERM");
  115.     
  116.   set_if_not ("PS1", primary_prompt);
  117.   set_if_not ("PS2", secondary_prompt);
  118.   set_if_not ("IFS", " \t\n");
  119.  
  120.   /* Magic machine types.  Pretty convenient. */
  121.   bind_variable ("HOSTTYPE", HOSTTYPE);
  122.  
  123.   /* Default MAILPATH, and MAILCHECK. */
  124.   set_if_not ("MAILCHECK", "60");
  125.   if ((get_string_value ("MAIL") == (char *)NULL) &&
  126.       (get_string_value ("MAILPATH") == (char *)NULL))
  127.     {
  128.       extern char *current_user_name;
  129.       char *tem;
  130.  
  131.       tem = (char *)xmalloc (1 + sizeof (DEFAULT_MAIL_PATH)
  132.                + strlen (current_user_name));
  133.       strcpy (tem, DEFAULT_MAIL_PATH);
  134.       strcat (tem, current_user_name);
  135.  
  136.       bind_variable ("MAILPATH", tem);
  137.       free (tem);
  138.     }
  139.  
  140.   /* Set up $PWD. */
  141.   {
  142.     char *get_working_directory (), *cd;
  143.  
  144.     cd = get_working_directory ("shell-init");
  145.     if (cd)
  146.       {
  147.     bind_variable ("PWD", cd);
  148.     free (cd);
  149.       }
  150.   }
  151.   
  152.   /* Do some things with shell level. */
  153.   {
  154.     extern int shell_level;
  155.     char new_level[10];
  156.     int old_level;
  157.  
  158.     set_if_not ("SHLVL", "0");
  159.     set_var_auto_export ("SHLVL");
  160.  
  161.     sscanf (get_string_value ("SHLVL"), "%d", &old_level);
  162.     shell_level = old_level + 1;
  163.     sprintf (new_level, "%d", shell_level);
  164.     bind_variable ("SHLVL", new_level);
  165.   }
  166.  
  167.   /* Get the full pathname to THIS shell, and set the BASH variable
  168.      to it. */
  169.   {
  170.     extern char *shell_name, *find_user_command (), *full_pathname ();
  171.     extern int login_shell;
  172.     char *tname = find_user_command (shell_name);
  173.     
  174.     if ((login_shell == 1) && (*shell_name != '/'))
  175.       {
  176.     struct passwd *entry = getpwuid (getuid ());
  177.  
  178.     if (entry)
  179.       {
  180.         /* If HOME doesn't exist, set it. */
  181.         temp_var = (SHELL_VAR *)find_variable ("HOME");
  182.         if (!temp_var)
  183.           {
  184.         temp_var = bind_variable ("HOME", entry->pw_dir);
  185.         temp_var->attributes |= att_exported;
  186.           }
  187.         name = savestring (entry->pw_shell);
  188.       }
  189.     else
  190.       name = savestring ("a.out");
  191.       }
  192.     else
  193.       {
  194.     if (!tname)
  195.       {
  196.         char *make_absolute ();
  197.         name = make_absolute (shell_name, get_string_value ("PWD"));
  198.       }
  199.     else
  200.       {
  201.         name = full_pathname (tname);
  202.         free (tname);
  203.       }
  204.       }
  205.  
  206.     /* Make the exported environment variable SHELL be whatever the name of
  207.        this shell is.  Note that the `tset' command looks at this variable
  208.        to determine what style of commands to output; if it ends in "csh",
  209.        then C-shell commands are output, else Bourne shell commands. */
  210.     set_if_not ("SHELL", name);
  211.     set_var_auto_export ("SHELL");
  212.  
  213.     /* Make a variable called BASH, which is the name of THIS shell. */
  214.     temp_var = bind_variable ("BASH", name);
  215.     temp_var->attributes |= att_exported;
  216.  
  217.     free (name);
  218.   }
  219.  
  220.   /* Make a variable called BASH_VERSION which contains the version info. */
  221.   {
  222.     char tt[12];
  223.     extern char *dist_version;
  224.     extern int build_version;
  225.  
  226.     sprintf (tt, "%s.%d", dist_version, build_version);
  227.     bind_variable ("BASH_VERSION", tt);
  228.   }
  229.  
  230.   /* Set history variables to defaults, and then do whatever we would
  231.      do if the variable had just been set. */
  232.   {
  233.     char *tilde_expand ();
  234.     char *tem = tilde_expand ("~/.bash_history");
  235.  
  236.     set_if_not ("HISTFILE", tem);
  237.     free (tem);
  238.  
  239.     set_if_not ("HISTSIZE", "500");
  240.     sv_histsize ("HISTSIZE");
  241.   }
  242.  
  243.   /* Gee, might as well get parent pid. */
  244.   {
  245.     char aval[10];
  246.  
  247.     sprintf (aval, "%d", getppid ());
  248.     bind_variable ("PPID", aval);
  249.   }
  250.  
  251.   non_unsettable ("PATH");
  252.   non_unsettable ("PS1");
  253.   non_unsettable ("PS2");
  254.   non_unsettable ("IFS");
  255.  
  256.   /* Get the users real user id, and save that in an readonly variable.
  257.      To make the variable *really* readonly, we have added it to a special
  258.      list of vars. */
  259.  
  260.   sv_uids ();
  261.   set_var_read_only ("UID");
  262.   set_var_read_only ("EUID");
  263.  
  264.   non_unsettable ("EUID");
  265.   non_unsettable ("UID");
  266. }
  267.  
  268. /* Add NAME to the list of variables that cannot be unset
  269.    if it isn't already there. */
  270. non_unsettable (name)
  271.      char *name;
  272. {
  273.   register int i;
  274.  
  275.   if (!non_unsettable_vars)
  276.     {
  277.       non_unsettable_vars = (char **)xmalloc (1 * sizeof (char *));
  278.       non_unsettable_vars[0] = (char *)NULL;
  279.     }
  280.  
  281.   for (i = 0; non_unsettable_vars[i]; i++)
  282.     if (strcmp (non_unsettable_vars[i], name) == 0)
  283.       return;
  284.  
  285.   non_unsettable_vars =
  286.     (char **)xrealloc (non_unsettable_vars, (2 + i) * sizeof (char *));
  287.   non_unsettable_vars[i] = savestring (name);
  288.   non_unsettable_vars[i + 1] = (char *)NULL;
  289. }
  290.  
  291. /* Set NAME to VALUE if NAME has no value. */
  292. set_if_not (name, value)
  293.      char *name, *value;
  294. {
  295.   char *temp = get_string_value (name);
  296.  
  297.   if (!temp)
  298.     bind_variable (n